using System;
using System.ComponentModel;
using System.Linq;
using Microsoft.WowAddonStudio.FrameXml.Serialization;
using Microsoft.WowAddonStudio.FrameXml.Serialization.LayoutFrames;

namespace Microsoft.WowAddonStudio.FrameXml.Components.Descriptors
{
    public static class FrameXmlTypeDescriptionProviderExtender
    {
        private static readonly Type[] extendableTypes = new[] { typeof(Backdrop), typeof(Texture), typeof(Anchor), typeof(Shadow), typeof(Color), typeof(FontString)};

        /// <summary>
        /// Extends the specified inheritable object.
        /// </summary>
        /// <param name="owner">The inheritable object.</param>
        /// <param name="propertyDescriptor">The property descriptor.</param>
        public static void Extend<T>(T owner, PropertyDescriptor propertyDescriptor) where T : class
        {
            FrameXmlTypeDescriptionProviderExtender.Extend(owner, owner, propertyDescriptor, propertyDescriptor.Name);
        }

        /// <summary>
        /// Extends the specified inheritable object.
        /// </summary>
        /// <param name="owner">The owner.</param>
        /// <param name="instance">The instance.</param>
        /// <param name="propertyDescriptor">The property descriptor.</param>
        /// <param name="propertyName">Name of the property.</param>
        private static void Extend<T>(T owner, object instance, PropertyDescriptor propertyDescriptor, string propertyName) where T : class
        {
            if (owner == null)
                throw new ArgumentNullException("owner");
            if (propertyDescriptor == null)
                throw new ArgumentNullException("propertyDescriptor");

            var propertyInstance = propertyDescriptor.GetValue(instance);

            if (extendableTypes.Contains(propertyDescriptor.PropertyType))
            {
                if (propertyInstance != null)
                    TypeDescriptor.AddProvider(new FrameXmlTypeDescriptionProvider<T>(TypeDescriptor.GetProvider(propertyDescriptor.PropertyType), owner, propertyName), propertyInstance);

                foreach (PropertyDescriptor childPropertyDescriptor in TypeDescriptor.GetProperties(propertyInstance))
                    FrameXmlTypeDescriptionProviderExtender.Extend(owner, propertyInstance, childPropertyDescriptor, propertyName);
            }
        }

        /// <summary>
        /// Extends the specified instance.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="instance">The instance.</param>
        public static void Extend<T>(T instance) where T : class
        {
            if (extendableTypes.Contains(typeof(T)))
                TypeDescriptor.AddProvider(new FrameXmlTypeDescriptionProvider<T>(TypeDescriptor.GetProvider(typeof(T)), instance), instance);
        }
    }
}